#include "HttpConnection.hpp"
#include "LogicSystem.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/beast/core/ostream.hpp>
#include <boost/beast/http/field.hpp>
#include <boost/beast/http/impl/read.hpp>
#include <boost/beast/http/impl/write.hpp>
#include <boost/beast/http/status.hpp>
#include <boost/beast/http/verb.hpp>
#include <boost/core/ignore_unused.hpp>
#include <chrono>
#include <exception>
#include <iostream>

HttpConnection::HttpConnection(net::io_context &ioc)
    : _socket(ioc), _deadline(ioc, std::chrono::seconds(60)) {}
void HttpConnection::Start() {
  auto self = shared_from_this();
  http::async_read(_socket, _buffer, _request,
                   [self](beast::error_code ec, std::size_t bytes) {
                     try {
                       if (ec) {
                         std::cerr << "http read err is " << ec.message()
                                   << "\n";
                         return;
                       }
                       boost::ignore_unused(bytes);
                       // 处理请求
                       self->HandleReq();
                       // 检查超时
                       self->checkDeadline();
                     } catch (std::exception &e) {
                       std::cerr << e.what() << "\n";
                       return;
                     }
                   });
}
void HttpConnection::HandleReq() {
  // 设置版本
  _response.version(_request.version());
  // 设置短链接
  _response.keep_alive(false);
  switch (_request.method()) {
    // 处理 GET 请求
  case http::verb::get: {
    // 参数解析
    PreParseGetParam();
    // 逻辑层处理请求内容
    bool success =
        LogicSystem::GetInstance()->HandleGet(_get_url, shared_from_this());
    if (!success) {
      _response.result(http::status::not_found);
      _response.set(http::field::content_type, "text/plain");
      beast::ostream(_response.body()) << "url not found\r\n";
      writeResponse();
      return;
    }
    _response.result(http::status::ok);
    _response.set(http::field::server, "GateServer");
    writeResponse();
    return;
  }
  // 处理 POST 请求
  case http::verb::post: {
    bool success = LogicSystem::GetInstance()->HandlePost(
        _request.target().to_string(), shared_from_this());
    if (!success) {
      _response.result(http::status::not_found);
      _response.set(http::field::content_type, "text/json");
      beast::ostream(_response.body()) << "url not found\r\n";
      writeResponse();
      return;
    }
    _response.result(http::status::ok);
    _response.set(http::field::server, "GateServer");
    writeResponse();
    return;
  }
  default:
    return;
  }
}
void HttpConnection::checkDeadline() {
  auto self = shared_from_this();
  _deadline.async_wait([self](boost::system::error_code ec) {
    if (!ec) {
      ec = self->_socket.close(ec);
      boost::ignore_unused(ec);
      return;
    }
  });
}
void HttpConnection::writeResponse() {
  // 回包
  auto self = shared_from_this();
  _response.content_length(_response.body().size());
  http::async_write(
      _socket, _response, [self](beast::error_code ec, ::std::size_t bytes) {
        boost::ignore_unused(bytes);
        std::cout << self->_request.target().to_string() << std::endl;
        self->_socket.shutdown(tcp::socket::shutdown_send);
        self->_deadline.cancel();
        return;
      });
}

// char 转为16进制
unsigned char HttpConnection::ToHex(unsigned char x) {
  return x > 9 ? x + 55 : x + 48;
}
// 16进制转10进制
unsigned char HttpConnection::FromHex(unsigned char x) {
  unsigned char y;
  if (x >= 'A' && x <= 'Z')
    y = x - 'A' + 10;
  else if (x >= 'a' && x <= 'z')
    y = x - 'a' + 10;
  else if (x >= '0' && x <= '9')
    y = x - '0';
  else
    assert(0);
  return y;
}
// url编码
std::string HttpConnection::UrlEncode(const std::string &str) {
  std::string strTemp = "";
  size_t length = str.length();
  for (size_t i = 0; i < length; i++) {
    // 判断是否仅有数字和字母构成
    if (isalnum((unsigned char)str[i]) || (str[i] == '-') || (str[i] == '_') ||
        (str[i] == '.') || (str[i] == '~'))
      strTemp += str[i];
    else if (str[i] == ' ') // 为空字符
      strTemp += "+";
    else {
      // 其他字符需要提前加%并且高四位和低四位分别转为16进制
      strTemp += '%';
      strTemp += ToHex((unsigned char)str[i] >> 4);
      strTemp += ToHex((unsigned char)str[i] & 0x0F);
    }
  }
  return strTemp;
}
// url解码
std::string HttpConnection::UrlDecode(const std::string &str) {
  std::string strTemp = "";
  size_t length = str.length();
  for (size_t i = 0; i < length; i++) {
    // 还原+为空
    if (str[i] == '+')
      strTemp += ' ';
    // 遇到%将后面的两个字符从16进制转为char再拼接
    else if (str[i] == '%') {
      assert(i + 2 < length);
      unsigned char high = FromHex((unsigned char)str[++i]);
      unsigned char low = FromHex((unsigned char)str[++i]);
      strTemp += high * 16 + low;
    } else
      strTemp += str[i];
  }
  return strTemp;
}

void HttpConnection::PreParseGetParam() {
  // 获取请求的 URI
  auto uri = _request.target();
  // 查找查询字符串的开始位置（即 '?' 的位置）
  auto query_pos = uri.find('?');
  if (query_pos == std::string::npos) {
    _get_url = uri.to_string();
    return;
  }
  _get_url = uri.substr(0, query_pos).to_string();
  std::string query_string = uri.substr(query_pos + 1).to_string();
  std::string key;
  std::string value;
  size_t pos = 0;
  while ((pos = query_string.find('&')) != std::string::npos) {
    auto pair = query_string.substr(0, pos);
    size_t eq_pos = pair.find('=');
    if (eq_pos != std::string::npos) {
      key = UrlDecode(
          pair.substr(0, eq_pos)); // 假设有 url_decode 函数来处理URL解码
      value = UrlDecode(pair.substr(eq_pos + 1));
      _get_params[key] = value;
    }
    query_string.erase(0, pos + 1);
  }
  // 处理最后一个参数对（如果没有 & 分隔符）
  if (!query_string.empty()) {
    size_t eq_pos = query_string.find('=');
    if (eq_pos != std::string::npos) {
      key = UrlDecode(query_string.substr(0, eq_pos));
      value = UrlDecode(query_string.substr(eq_pos + 1));
      _get_params[key] = value;
    }
  }
}

net::ip::tcp::socket &HttpConnection::GetSocket() { return _socket; }